#include <stdio.h>
#include <string.h>
#include <dos.h>
#include "mpx_supt.h"
#include "dcb.h"
#include "interrupt5a.h"

#define PIC_MASK 0x21
#define BAUD_RATE_DIVISOR_LSB 0x3F8
#define BAUD_RATE_DIVISOR_MSB 0x3F9

int com_open(int *eflag_p, int baud_rate);
int com_close(void);
int com_read(char *buf_p, int *count_p);
int com_write(char *buf_p, int *count_p);
mpx_dcb pDCB;

void interrupt (*oldhandler)();
//void name();

int mask;

int com_open(int *eflag_p, int baud_rate)
{
	
	if(eflag_p == NULL)
		return -101;
	if(baud_rate <= 0)
		return -102;
	if(pDCB.flag ==OPEN)
		return -103;
	else
	{	/* DCB initializtion */  
		int baud_rate_devisor;
	   
		pDCB.state = IDLE;
		pDCB.flag = OPEN;
		pDCB.e_flag = eflag_p; 

		oldHandler = getvect(COM1_IR_ID );
		setvect (COM1_IR_ID,detectHandler);

		baud_rate_divisor = 115200 / (long) baud_rate;
		outportb(COM1_BASE+3, 0x80);
		outportb(BAUD_RATE_DIVISOR_LSB,baud_rate_divisor & 0xFF);
		outportb(BAUD_RATE_DIVISOR_MSB,(baud_rate_divisor  >> 8) & 0xFF);
		outportb(COM1_BASE+3, 0x03);

		disable();
		mask = inportb(PIC_MASK);
		mask = mask & ~0x80;
		outportb(PIC_MASK, mask);
		enable();

		outportb(COM1_BASE+4, 0x08);
		outportb(COM1_BASE+7, 0x01);
		//stores 0x08 in modem control register to enable serial interrupt
		//stores 0x01 in the interrupt enable register to enable input ready interrupts
		return 0;
	}
}

int com_close(void)
{
	if(pDCB.flag != OPEN)
	{
		return -201;
	}
	else
	{
		disable();
		mask = inportb(PIC_MASK);
		mask = mask | 0x10;
		outportb(PIC_MASK, mask);
		enable();

		//loads 0x00 into modem status and interrupt inable registers, disable ACC interrupts
		//restore original interrupts using setvect()

		outportb(COM1_BASE+4, 0x00);
		outportb(COM1_BASE+7, 0x00);

		return 0;
	}
}

int com_read(char *buf_p, int *count_p)
{
	char a[count_p];
	a = gets(*buf_p);

	if(pDCB.flag != OPEN)
	{
		return -301;
	}

	if(buf_p == NULL)
	{
		return -302;
	}

	if(count_p == NULL)
	{
		return -303;
	}
	if(pDCB.state != IDLE)
	{
		return -304;
	}
	else
	{
		pDCB.in_buffer = buf_p;
		pDCB.in_count = count_p;
		pDCB.in_done = 0;
		pDCB.eflag_p = 0;
		pDCB.state = READ;
		//get chars from ring buffer
		//re-enable interrupts

		if(pDCB.in_done < pDCB.in_count)
		{
			pDCB.state = READ;
			com_read( , count_p + 1);
		}

		if(*pDCB.in_buffer-1 == '\r')
		{
			pDCB.in_buffer-1 = '\0';
		}

		else
			dcb.in_buffer = '\0';

		pDCB.state = IDLE;
		pDCB.eflag_p = 0;
		pDCB.in_count = pDCB.in_done;
	}
	return 0;
}

int com_write(char *buf_p, int *count_p)
{
	
	if(pDCB.flag != OPEN)
	{
		return -401;
	}

	if(buf_p == NULL)
	{
		return -402;
	}

	if(count_p == NULL)
	{
		return -403;
	}
	if(pDCB.state != IDLE)
	{
		return -404;
	}
	else
	{
		pDCB.in_buffer = buf_p;
		pDCB.in_count = count_p;
		pDCB.in_done = 0;

		pDCB.state = WRITE;
		pDCB.eflag_p = 0;
		outportb(COM1_BASE, *pDCB.in_buffer);

		pDCB.in_buffer++;
		pDCB.indone++;

		disable();
		mask = inportb(COM1_INT_EN);
		mask = mask | 0x02;
		outportb(COM1_INT_EN,mask);
		enable();
		return 0;
	}
}